package com.guardchina.framework.web;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.guardchina.framework.util.constant.Constants;
import com.guardchina.framework.util.constant.HeaderKeyConst;
import com.guardchina.framework.web.converter.LocalDateConverter;
import com.guardchina.framework.web.converter.LocalDateTimeConverter;
import com.guardchina.framework.web.converter.LocalTimeConverter;
import com.guardchina.framework.web.filter.Slf4jTraceFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.convert.converter.Converter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * 描述：web mvc 配置
 *
 * @author lwb
 * @date 2019/3/15 13:54
 */
@Slf4j
public class WebMvcConfiguration{

    /**
    *  跨域访问
    **/
    @Bean
    public FilterRegistrationBean corsFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addExposedHeader(getExposeHeader());
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }

    private String getExposeHeader(){
        return HeaderKeyConst.TOKEN_KEY + "," + HeaderKeyConst.USER_ID_KEY +
                "," + HeaderKeyConst.TOKEN_REFRESH_KEY +
                "," + HeaderKeyConst.TOKEN_GET_KEY;
    }

    @Bean
    public FilterRegistrationBean logTraceFilterRegistration(){
        FilterRegistrationBean<Slf4jTraceFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new Slf4jTraceFilter());
        registration.addUrlPatterns("/*");
        registration.setName("logTraceFilter");
        registration.setOrder(1);
        return registration;
    }

    @Bean
    public ObjectMapper objectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_TIME_PATTERN)));
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_PATTERN)));
        javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_TIME_PATTERN)));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_TIME_PATTERN)));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_DATE_PATTERN)));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(Constants.DEFAULT_TIME_PATTERN)));

        objectMapper.registerModule(javaTimeModule);

        objectMapper.setDateFormat(new SimpleDateFormat(Constants.DEFAULT_DATE_TIME_PATTERN));

        return objectMapper;
    }

    @Bean
    public Converter localDateTimeConverter(){
        return new LocalDateTimeConverter();
    }

    @Bean
    public Converter localDateConverter(){
        return new LocalDateConverter();
    }

    @Bean
    public Converter localTimeConverter(){
        return new LocalTimeConverter();
    }

}
